//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <bsp.h>
#include <init.h>
#include "pic.h"
#include <timer.h>

EXTERN_C DECL_CODEINIT void CDECL InitPIC()
{
    int i;
	for(i=0;i<32;i++)
		Outl((ioport_t)((int)VIC0VECTADDR+4*i), i);

	for(i=0;i<32;i++)
		Outl((ioport_t)((int)VIC1VECTADDR+4*i), i+32);

	rVIC0INTSELECT = 0x0;
	rVIC1INTSELECT = 0x0;
	rVIC0ADDR = 0;
	rVIC1ADDR = 0;

    //there's no need to clear status reg in 6410

    BspMaskAllIrqs(FALSE);
}

EXTERN_C irqs_t CDECL BspGetIrqs()
{
    return (irqs_t)rVIC0IRQSTATUS | ((irqs_t)rVIC1IRQSTATUS << 32);
}

INLINE void EndOfInterrupt(irq_t irq)
{
    switch (irq) {
    case PIT_Irq: EndOfPITInterrupt(); break;

    // TODO: add EOI codes for other devices
    }
}

STATIC irqs_t s_irqMask = 0;

#if defined(_GNUC)


#define LLCONST(n)  n##ll
#elif defined(_EVC)

#define LLCONST(n)  n

#else

#error Unknown C++ compiler

#endif // defined(_GNUC)

EXTERN_C void CDECL BspMaskIrqs(irqs_t irqs, bool_t bEnable)
{
    if (bEnable) {
        if (irqs & LLCONST(0x00000000ffffffff)) {
            rVIC0INTENABLE = (uint32_t)irqs;
        }
        if (irqs & LLCONST(0xffffffff00000000)) {
            rVIC1INTENABLE = (uint32_t)(irqs >> 32);
        }
    }
    else {
        if (irqs & LLCONST(0x00000000ffffffff)) {
            rVIC0INTENCLEAR = (uint32_t)irqs;
        }
        if (irqs & LLCONST(0xffffffff00000000)) {
            rVIC1INTENCLEAR = (uint32_t)(irqs >> 32);
        }
    }
}

EXTERN_C void CDECL BspMaskAllIrqs(bool_t bEnable)
{
    s_irqMask = LLCONST(0xffffffff);

    if (bEnable) {
    	rVIC0INTENABLE = (uint32_t)s_irqMask;
    	rVIC1INTENABLE = (uint32_t)s_irqMask;
    }
    else {
    	rVIC0INTENCLEAR = (uint32_t)s_irqMask;
    	rVIC1INTENCLEAR = (uint32_t)s_irqMask;
    }
}

EXTERN_C void CDECL BspAcknowledgeIrq(irq_t irq)
{
    EndOfInterrupt(irq);
}
